﻿/*! @File           : main.cpp
 *  @Brief          : 简要说明
 *  @Details       : 详细说明
 *  @Author       : wulifeng
 *  @Date          : 2023-03-01 14:37:15
 *  @Version      : v1.0
 *  @Copyright   : Copyright By wlf, All Rights Reserved
 */
#include "qtmaterial.h"
#include <QFile>
#include <QXmlStreamReader>
#include <QDebug>
#include <QRegularExpressionMatchIterator>
#include <QJsonDocument>
#include <QJsonArray>
#include <QJsonObject>
#include <QJsonParseError>
#include <QDir>
#include <QCoreApplication>

QtMaterial::QtMaterial(QObject* parent) : QObject(parent)
{

}

QtMaterial::~QtMaterial()
{

}


bool QtMaterial::Init_Template()
{
    template_path=":/style/material.css.template";
    QFile file(template_path);
    if(!file.open(QIODevice::ReadOnly))
    {
        qDebug() << "setTemplate_path err";
        return  false;
    }
    template_content = file.readAll();
    file.close();

    QRegularExpression re("\\{\\{(.*?)\\}\\}");
    QRegularExpressionMatchIterator i = re.globalMatch(template_content);

    while(i.hasNext())
    {
        QRegularExpressionMatch match = i.next();

        if(!template_strs.contains(match.captured(0)))
        {
            template_strs.append(match.captured(0));
        }
    }
    return  true;
}


bool QtMaterial::Init_Themeconf(QString theme)
{
    QString path=":/style/theme/";
    QDir dir(":/style/theme/");
    if(!dir.exists())
    {
        qDebug() << "setThreme_xml_path err";
        return  false;
    }

    for(auto fileName : dir.entryList())
    {
        if(fileName.endsWith(".xml"))
            thremes<<fileName;
    }

    if(thremes.contains(theme))
    {
        threme_name = theme;;
    }
    else
    {
        threme_name=dir.entryList().at(0);
    }

    QFile color_extra_conf_file(path+threme_name);
    if(!color_extra_conf_file.open(QIODevice::ReadOnly | QIODevice::Text))
    {
    }
    QXmlStreamReader reader(&color_extra_conf_file);  // 创建XML读取器

    while(!reader.atEnd() && !reader.hasError())    // 循环读取XML内容
    {
        QXmlStreamReader::TokenType token = reader.readNext();
        if(token == QXmlStreamReader::StartElement && reader.name().toString() != "resources")
        {
            QString attr;
            QString value;
            QXmlStreamAttributes attributes = reader.attributes();
            for(const QXmlStreamAttribute& attribute : attributes)
            {
                attr =  attribute.value().toString();
            }
            token = reader.readNext();
            if(token == QXmlStreamReader::Characters)
            {
                value = reader.text().toString().trimmed();
            }

            color_extra_conf.insert(attr, value);
            token = reader.readNext();
        }
    }

    if(reader.hasError())    // 检查读取器是否出错
    {
        qDebug() << "XML Error: " << reader.errorString();
    }
    color_extra_conf_file.close();  // 关闭文件
    return  true;
}



bool QtMaterial::Init_Extraconf()
{
    extra_conf_path=":/style/extraconfig.json";
    QFile file(extra_conf_path);
    if(!file.open(QIODevice::ReadOnly | QIODevice::Text))
    {
        qDebug() << "Failed to open file";
        return  false;
    }
    QByteArray jsondata = file.readAll();
    file.close();
    QJsonParseError err;
    QJsonDocument doc = QJsonDocument::fromJson(jsondata, &err);

    if(err.error != QJsonParseError::NoError)
    {
        qDebug() << "JSON文件解析错误";
        return  false;
    }

    QJsonObject obj = doc.object();

    QString danger = obj.value("danger").toString("#dc3545");
    QString warning = obj.value("warning").toString("#ffc107");
    QString success = obj.value("success").toString("#17a2b8");
    QString font_family = obj.value("font_family").toString("#monoespace");
    QString font_size = obj.value("font_size").toString("13px");
    QString line_height = obj.value("line_height").toString("13px");
    QString density_scale = obj.value("density_scale").toString("3");
    QString density_interval = obj.value("density_interval").toString("1");
    QString qmenu_height = obj.value("qmenu_height").toString("20px");
    QString qmenu_padding = obj.value("qmenu_padding").toString("2px");
    QString border = obj.value("border").toString("0");
    QString scale = obj.value("scale").toString("1");

    color_extra_conf.insert("danger", danger);
    color_extra_conf.insert("warning", warning);
    color_extra_conf.insert("success", success);
    color_extra_conf.insert("font_family", font_family);
    color_extra_conf.insert("font_size", font_size);
    color_extra_conf.insert("line_height", line_height);
    color_extra_conf.insert("density_scale", density_scale);
    color_extra_conf.insert("density_interval", density_interval);
    color_extra_conf.insert("qmenu_height", qmenu_height);
    color_extra_conf.insert("qmenu_padding", qmenu_padding);
    color_extra_conf.insert("border", border);
    color_extra_conf.insert("scale", scale);
    return  true;
}


bool QtMaterial::gen_svg_res()
{
    QString primary, secondary, disabled, active;
    primary = color_extra_conf.value("primaryColor");          //primary   1
    secondary = color_extra_conf.value("secondaryColor");      //secondary 2
    disabled = color_extra_conf.value("primaryLightColor");    //disabled  3
    active = "#707070";




    SVG_Original_path=":/style/original/";
    QString active_svg = Gen_path + "/active";
    QString disabled_svg = Gen_path + "/disabled";
    QString primary_svg = Gen_path + "/primary";

    QDir dir(active_svg);
    if(!dir.exists())
    {
        dir.mkdir(active_svg);
    }
    QDir dir1(disabled_svg);
    if(!dir1.exists())
    {
        dir1.mkdir(disabled_svg);
    }
    QDir dir2(primary_svg);
    if(!dir2.exists())
    {
        dir2.mkdir(primary_svg);
    }

    QMap<QString, QString> svg_color;
    svg_color.insert(disabled_svg, disabled);
    svg_color.insert(primary_svg, primary);
    svg_color.insert(active_svg, active);

    QDir svg_original(SVG_Original_path);
    QStringList svgs = svg_original.entryList();
    for(int i = 0; i < svgs.length(); i++)
    {
        if(!svgs.at(i).contains(".svg"))
        {
            continue;
        }
        QFile svgfile(SVG_Original_path + "/" + svgs.at(i));
        qDebug() << "inpath :" << SVG_Original_path + "/" + svgs.at(i);
        if(!svgfile.open(QIODevice::ReadOnly))
        {
            return false;
        }
        QString svg_content_ori = svgfile.readAll();
        svgfile.close();

        qDebug() << svgs.at(i);
        for(QString path : svg_color.keys())
        {
            QString key = svg_color.value(path);
            QString svg_content = svg_content_ori;
            svg_content = replace_color(svg_content, key);
            qDebug() << "blue replace to key:" << key;
            svg_content = replace_color(svg_content, secondary, "#ff0000");
            qDebug() << "red replace to sec:" << secondary;
            //写文件
            qDebug() << path + "/" + svgs.at(i);
            QFile file(path + "/" + svgs.at(i));
            if(!file.open(QIODevice::WriteOnly))
            {
                return false;
            }
            file.write(svg_content.toLatin1());
            file.close();
        }
    }
    return true;
}

QString QtMaterial::replace_color(QString content, QString replace, QString color)
{
    QString c;
    QStringList colors;
    colors.append(color);
    for(int i = 1; i < 7; i++)
    {
        c = color;
        colors.append(c.insert(i, '\n'));
        //qDebug() << c;
    }
    for(QString c : colors)
    {
        content.replace(c.toLatin1(), replace.toLatin1());
    }

    //把黑色替换透明
    replace = "#ffffff00";
    color = "#000000";
    colors.clear();
    colors.append(color);
    for(int i = 1; i < 7; i++)
    {
        c = color;
        colors.append(c.insert(i, '\n'));
        //qDebug() << c;
    }
    for(QString c : colors)
    {
        content.replace(c.toLatin1(), replace.toLatin1());
    }
    return content;
}

bool QtMaterial::templatestrs_to_realval()
{
    QString temp ;
    QStringList ts;

    //遍历待替换字符串表，获取实际值
    for(auto tempstr : template_strs)
    {
        //模板字符串转换为实际字符串
        QString real_str;
        if(!(tempstr.contains("|") || tempstr.contains("(") || tempstr.contains("(")))
        {
            real_str.clear();
            for(auto value : color_extra_conf.keys())
            {

                if(tempstr.contains(value))
                {
                    real_str = color_extra_conf.value(value);
                }
            }
        }
        else if(tempstr.contains("|") && tempstr.contains("(") && tempstr.contains("("))
        {
            temp = tempstr.mid(2, tempstr.length() - 4);
            ts = temp.split(QRegExp("[\\|\\(|\\)|\\,]"));
            if(ts.contains("density"))
            {
                double value = 0;
                double density_scale = 0;
                double border = 0;
                double scale = 1;
                double density_interval = 0;
                double _min = 4;

                if(color_extra_conf.contains(ts.at(0)))
                {
                    value = color_extra_conf.value(ts.at(0)).toDouble();
                }
                else
                {
                    value = ts.at(0).toDouble();
                }
                for(int i = 0; i < ts.length(); i++)
                {
                    QString str = ts.at(i);
                    if(i == 0 || str == "density")
                    {
                        continue;
                    }
                    if(str.contains("density_scale"))
                    {
                        if(str.contains("="))
                        {
                            density_scale = str.split("=").at(1).toDouble();
                        }
                        else
                        {
                            density_scale = color_extra_conf.value("density_scale").toDouble();
                        }
                    }
                    if(str.contains("border"))
                    {
                        if(str.contains("="))
                        {
                            border = str.split("=").at(1).toDouble();
                        }
                        else
                        {
                            border = color_extra_conf.value("border").toDouble();
                        }
                    }
                    if(str.contains("scale"))
                    {
                        if(str.contains("="))
                        {
                            scale = str.split("=").at(1).toDouble();
                        }
                        else
                        {
                            scale = color_extra_conf.value("scale").toDouble();
                        }
                    }
                    if(str.contains("density_interval"))
                    {
                        if(str.contains("="))
                        {
                            density_interval = str.split("=").at(1).toDouble();
                        }
                        else
                        {
                            density_interval = color_extra_conf.value("density_interval").toDouble();
                        }
                    }
                }
                //qDebug() << temp << value << scale << density_scale << density_interval << border;
                value += scale * (density_scale * density_interval - border * 2);

                if(value < 0)
                {
                    value = _min;
                }
                real_str = QString().setNum(value);
                //qDebug() << ts << real_str;
            }
            else if(ts.contains("opacity"))//透明度
            {
                QString color, r, g, b;
                int rcolor, gcolor, bcolor;
                for(QString str : ts)
                {
                    if(color_extra_conf.keys().contains(str))
                    {
                        //qDebug() << str << color_extra_conf.value(str);
                        color = color_extra_conf.value(str);
                        color = color.mid(1, color.length() - 1);
                        bool flag;
                        r = "0x" + color.mid(0, 2);
                        g = "0x" + color.mid(2, 2);
                        b = "0x" + color.mid(4, 2);

                        rcolor = r.toInt(&flag, 16);
                        if(!flag)
                        {
                            qDebug() << "转换颜色失败";
                            return false;
                        }
                        gcolor = g.toInt(&flag, 16);
                        if(!flag)
                        {
                            qDebug() << "转换颜色失败";
                            return false;
                        }
                        bcolor = b.toInt(&flag, 16);
                        if(!flag)
                        {
                            qDebug() << "转换颜色失败";
                            return false;
                        }
                    }
                    else if(str == "opacity" || str.isEmpty())
                    {
                        continue;
                    }
                    else
                    {
                        bool flag;
                        int op =  str.toDouble(&flag) * 255;
                        if(!flag)
                        {
                            qDebug() << "透明度入参错误";
                            return false;
                        }
                        real_str = QString("rgba(%1,%2,%3,%4)").arg(rcolor).arg(gcolor).arg(bcolor).arg(op);
                    }
                }
            }
            else
            {
                qDebug() << "未定义的模版" << ts;
                return false;
            }
        }
        templata_str_replace.insert(tempstr, real_str);
    }
    return true;
}

QStringList QtMaterial::getThremes() const
{
    return thremes;
}

void QtMaterial::setThremes(const QStringList &value)
{
    thremes = value;
}

bool  QtMaterial::make_Style_sheet( QString &style_sheet,QString theme,bool saveQss)
{
    //创建输出路径
    Gen_path = QCoreApplication::applicationDirPath()+ "/style/svg";
    QDir dir(Gen_path);
    if(!dir.exists())
        dir.mkpath(Gen_path);


    if(!Init_Template())
    {
        return false;
    }
    if(! Init_Extraconf())
    {
        return false;
    }
    if(!Init_Themeconf(theme))
    {
        return false;
    }
    if(!gen_svg_res())
    {
        return false;
    }
    if(!templatestrs_to_realval())
    {
        return false;
    }

    style_sheet=template_content;

    for(QString temp : templata_str_replace.keys())
    {
        style_sheet.replace(temp, templata_str_replace.value(temp));
    }

    if(saveQss)
    {
        QFile file(Gen_path+threme_name.replace(".xml",".qss"));
        if(!file.open(QIODevice::WriteOnly))
        {
            return false;
        }
        file.write(style_sheet.toLatin1());
        file.close();
    }

    return true;
}
